package com.coderush.admin.sys.service.impl;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.coderush.admin.core.component.SnowflakeIdGenerator;
import com.coderush.admin.core.config.AdminRoleConfig;
import com.coderush.admin.core.utils.UserContext;
import com.coderush.admin.core.utils.UserContextModel;
import com.coderush.admin.sys.dao.MenuDao;
import com.coderush.admin.sys.dao.RoleMenuDao;
import com.coderush.admin.sys.exception.MenuException;
import com.coderush.admin.sys.model.dto.MenuAddDto;
import com.coderush.admin.sys.model.dto.MenuUpdateDto;
import com.coderush.admin.sys.model.entity.Menu;
import com.coderush.admin.sys.model.entity.RoleMenu;
import com.coderush.admin.sys.model.vo.MenuLeftVo;
import com.coderush.admin.sys.model.vo.MenuVo;
import com.coderush.admin.sys.model.vo.UserRoleVo;
import com.coderush.admin.sys.service.MenuService;
import com.coderush.admin.sys.mapper.MenuMapper;
import com.coderush.admin.utils.MenuHelper;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;

/**
* @author Administrator
* @description 针对表【sys_menu(系统菜单)】的数据库操作Service实现
* @createDate 2025-08-29 15:40:45
*/
@Service
public class MenuServiceImpl extends ServiceImpl<MenuMapper, Menu> implements MenuService{

    @Resource
    private MenuDao menuDao;
    @Resource
    private SnowflakeIdGenerator snowflakeIdGenerator;
    @Resource
    private RoleMenuDao roleMenuDao;

    @Resource
    private AdminRoleConfig adminRoleConfig;

    /**
     * 查询左侧菜单
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<MenuLeftVo> findLeftMenu() throws Exception {

        List<MenuVo> menuVoList = null;
        List<Menu> lst = null;

        // 获取当前操作用户的角色
        UserContextModel user = UserContext.getUser();
        // 如果当前用户是超级管理员
        if (user.getIsAdmin()) {
            // 查询所有菜单
            lst = menuDao.findAllMenuTypeMenuAndFunction();
            if (CollectionUtils.isEmpty(lst)) {
                throw MenuException.menuNotExist();
            }

            menuVoList = JSONArray.parseArray(JSON.toJSONString(lst), MenuVo.class);
            // 构建树形菜单
            menuVoList =  MenuHelper.buildTree(menuVoList);
            return this.buildMenus(menuVoList);
        }

        // 如果当前用户不是超级管理员，则查询role - menu 中所分配的菜单
        // 用户可能有多个角色(用户对应的角色)
        List<UserRoleVo> userRoleList = user.getUserRoleVoList();
        // 如果用户没有角色
        if (CollectionUtils.isEmpty(userRoleList)) {
            throw MenuException.noRoleAndMenu();
        }

        // 查询用户所有的角色对应的所有的菜单
        // 用户对应的所有角色
        List<Long> roleIds = new ArrayList<>();
        userRoleList.stream().forEach(userRole -> {
            roleIds.add(userRole.getRoleId());
        });
        // 角色下的所有菜单 role_menu 表
        List<Long> menuIds = roleMenuDao.findByRoleIds(roleIds);
        if (CollectionUtils.isEmpty(menuIds)) {
            throw MenuException.noRoleAndMenu();
        }
        // 根据菜单IDs 查询菜单
        lst = menuDao.findMenuTypeMenuAndFunction(menuIds);
        if (CollectionUtils.isEmpty(lst)) {
            throw MenuException.menuNotExist();
        }

        menuVoList = JSONArray.parseArray(JSON.toJSONString(lst), MenuVo.class);

        // 构建树形菜单
        menuVoList =  MenuHelper.buildTree(menuVoList);

        return this.buildMenus(menuVoList);
    }

    private List<MenuLeftVo> buildMenus(List<MenuVo> menuList) {

        List<MenuLeftVo> leftMenuVoList = new LinkedList<MenuLeftVo>();

        if (!CollectionUtils.isEmpty(menuList)) {
            for (MenuVo menu : menuList) {
                MenuLeftVo menuLeftVo = new MenuLeftVo();
                menuLeftVo.setId(menu.getId());
                menuLeftVo.setMenuName(menu.getMenuName());
                menuLeftVo.setMenuType(menu.getMenuType());
                menuLeftVo.setMenuHref(menu.getMenuHref());
                menuLeftVo.setMenuIcon(menu.getMenuIcon());
                menuLeftVo.setMenuSort(menu.getMenuSort());
                if (!CollectionUtils.isEmpty(menu.getChildren())) {
                    menuLeftVo.setChildren(this.buildMenus(menu.getChildren()));
                }

                leftMenuVoList.add(menuLeftVo);
            }
        }

        return leftMenuVoList;
    }


    /**
     * 查询菜单树
     *
     * @return
     * @throws Exception
     */
    @Override
    public List<MenuVo> findMenuTree() throws Exception {

        List<MenuVo> menuList = null;
        List<Menu> lst = null;

        // 获取当前操作用户的角色
        UserContextModel user = UserContext.getUser();
        // 如果当前用户是超级管理员
        if (user.getIsAdmin()) {
            // 查询所有菜单
            lst = menuDao.findAllMenu();
            if (CollectionUtils.isEmpty(lst)) {
                throw MenuException.menuNotExist();
            }

            menuList = JSONArray.parseArray(JSON.toJSONString(lst), MenuVo.class);
            // 构建树形菜单
            return MenuHelper.buildTree(menuList);
        }

        // 如果当前用户不是超级管理员，则查询role - menu 中所分配的菜单
        // 用户可能有多个角色(用户对应的角色)
        List<UserRoleVo> userRoleList = user.getUserRoleVoList();
        // 如果用户没有角色
        if (CollectionUtils.isEmpty(userRoleList)) {
            throw MenuException.noRoleAndMenu();
        }

        // 查询用户所有的角色对应的所有的菜单
        // 用户对应的所有角色
        List<Long> roleIds = new ArrayList<>();
        userRoleList.stream().forEach(userRole -> {
            roleIds.add(userRole.getRoleId());
        });
        // 角色下的所有菜单 role_menu 表
        List<Long> menuIds = roleMenuDao.findByRoleIds(roleIds);
        if (CollectionUtils.isEmpty(menuIds)) {
            throw MenuException.noRoleAndMenu();
        }
        // 根据菜单IDs 查询菜单
        lst = menuDao.getByIds(menuIds);
        if (CollectionUtils.isEmpty(lst)) {
            throw MenuException.menuNotExist();
        }

        menuList = JSONArray.parseArray(JSON.toJSONString(lst), MenuVo.class);

        // 构建树形菜单
        return MenuHelper.buildTree(menuList);
    }

    /**
     * 修改菜单
     * @param updateDto
     * @return
     * @throws Exception
     */
    @Override
    public Boolean update(MenuUpdateDto updateDto) throws Exception {

        // 菜单是否存在
        Menu menuDB = menuDao.getById(updateDto.getId());
        if (menuDB == null) {
            throw MenuException.menuNotExist();
        }

        // 菜单名称不能重复，查询排除此菜单的数据，是否含有相同名称的菜单
        // 如果为空，则修改了菜单名称，并且菜单名称是不重复的，这是允许的
        Menu secondMenu = menuDao.getByMenuName(updateDto.getMenuName());
        if (secondMenu != null && !Objects.equals(secondMenu.getId(), menuDB.getId())) {
            throw MenuException.repeatMenuName();
        }

        var menu = JSON.parseObject(JSON.toJSONString(updateDto), Menu.class);
        return  menuDao.update(menu);
    }

    /**
     * 添加菜单
     * @param addDto
     * @return
     * @throws Exception
     */
    @Override
    public Boolean add(MenuAddDto addDto) throws Exception {

        // 菜单编码不能重复
        Menu menuDB = menuDao.getByMenuCode(addDto.getMenuCode());
        if (menuDB != null) {
            throw MenuException.repeatMenuCode();
        }
        // 菜单名称不能重复
        menuDB = menuDao.getByMenuName(addDto.getMenuName());
        if (menuDB != null) {
            throw MenuException.repeatMenuName();
        }

        var menu = JSON.parseObject(JSON.toJSONString(addDto), Menu.class);
        menu.setId(snowflakeIdGenerator.nextId());
        boolean flag = menuDao.add(menu);

        // 如果当前用户是超级管理员，则新增超级管理员的菜单
        UserContextModel user = UserContext.getUser();
        if (user.getIsAdmin()) {
            RoleMenu roleMenu = new RoleMenu();
            roleMenu.setRoleId(adminRoleConfig.getId());
            roleMenu.setMenuId(menu.getId());
            roleMenu.setIsHalf(0);
            roleMenuDao.add(roleMenu);
        }

        return flag;
    }
}




